librerias

Bases de letras filtradas por idioma

# lyrics = mongo(collection = "lyrics", db = "spotify_dm" )
# df_lyrics <- lyrics$find('{}')
# 
# write.csv(df_lyrics, "data/df_lyrics.csv")


df_lyrics <- read.csv("data/df_lyrics.csv") %>% 
  select(-X)

df_lyrics_unicas <- df_lyrics %>% 
  distinct(artist_name, track_name, lyrics)


#filtro de idioma
spa_lyrics = df_lyrics_unicas[textcat(df_lyrics_unicas$lyrics)=="spanish",]
spa_lyrics

en_lyrics = df_lyrics_unicas[textcat(df_lyrics_unicas$lyrics) %in% c("english", "scots"),]
en_lyrics

#chequeo cantidad de canciones por idioma
100*(nrow(en_lyrics) + nrow(spa_lyrics))/nrow(df_lyrics_unicas)
[1] 89.86784
# tabla contingencia de idiomas
idiomas = textcat(df_lyrics_unicas$lyrics)
sort(table(idiomas), decreasing = T)
idiomas
       english          scots        spanish         german middle_frisian        catalan     portuguese         french 
           528            527            169             46             37             22              8              7 
       italian         breton           manx        frisian      rumantsch        turkish 
             6              5              3              2              1              1 

limpieza español

inspect(corpus.pro[1])
Error in (function (classes, fdef, mtable)  : 
  unable to find an inherited method for function ‘inspect’ for signature ‘"SimpleCorpus"’

limpieza ingles

head(en_lyrics$lyrics, 1)
[1] "look good together reason watch night long yeah know will turn heads forever tonight gonna show walking watch whole room change baby baby play blame confidenceoh blame measurements shut shit sight right dripping finesse make sense dripping finesse know know dripping finesse make sense dripping finesse know know now slow baby love way feels grind yeah connection magnetic floor nothing can stop us tonight walking watch whole room change baby baby play blame confidenceoh blame measurements shut shit sight right dripping finesse make sense dripping finesse know know dripping finesse make sense dripping finesse know know fellas grab ladies lady fine tell one one life woo ladies grab fellas let right right one like mind ow yeah got going got going feel good us ayy yeah got going got going yeah girl got going yeah got going got going hey feel good us ayy feels good yeah got going got going dripping finesse dripping make sense dripping finesse know know dripping finesse baby make sense dripping finesse know know yeah know got going yeah got going got going feel good us ayy yeah got going got going know know yeah got going got going girl got feel good us ayy yeah got going got going know know"

Explicit

Español

#Diccionario español
malas_palabras_1 <- read_csv("data/malas_palabras.txt", 
    col_names = FALSE)

malas_palabras_2 <- read_csv("data/malas_palabras_translate.txt", 
    col_names = FALSE)

malas_palabras_3 <- read_csv("data/malas_palabras_wiki.txt", 
    col_names = FALSE) %>% 
  select(X1)

malas_palabras_4 <- read_csv("data/palabras_profanas_es.txt", 
                             col_names = FALSE)

malas_palabras <- rbind(malas_palabras_1, malas_palabras_2,
                        malas_palabras_3, malas_palabras_4)


#Función para limpiar. 
text_cleaning_esp = function(txt, stop=FALSE){
  txt = sub('^.+?\\[.*?\\]',"", txt) #ok
  txt = sub("More on Genius.*","", txt)
  txt = gsub('\\[.*?\\]', '', txt)
  txt = gsub("\\n"," ", txt)
  txt = gsub("[()]", " ", txt)
  txt = tolower(txt)
  # txt = decontracted(txt)
  txt = gsub("\\W+\\b", " ", txt)
  txt = gsub("\\d", " ", txt)
  txt = str_trim(txt)
  # txt = stri_trans_general(txt, "Latin-ASCII")
  return(txt)
}


malas_palabras$limpias = text_cleaning(malas_palabras$X1)
malas_palabras

malas_palabras %>% filter(startsWith(limpias, "g"))

Inglés

matriz término documento

frecuencia de términos

# Dataframe con frecuencia de terminos (de rows)
dtm_to_freq <- TermDocumentMatrix(corpus.pro, control = list(weighting =  "weightTf"))
matriz_td_to_freq <- as.matrix(dtm_to_freq)
freq_term <- sort(rowSums(matriz_td_to_freq), decreasing=TRUE )
df_freq <- data.frame(termino = names(freq_term), frecuencia=freq_term)
row.names(df_freq) <- NULL
head(df_freq)


## Graficos de terminos
N=15
barplot(df_freq[1:N,]$frecuencia, las = 2, names.arg = df_freq[1:N,]$termino,
        col ="lightblue", main ="Palabras más frecuentes",
        ylab = "Frecuencia de palabras", ylim = c(0, max(df_freq$frecuencia)+300))


topK = head(df_freq, 100)

# Visualización de los resultados
# Nube de Etiquetas
library("wordcloud")
library("RColorBrewer")

par(bg="grey30") # Fijamos el fondo en color gris

set.seed(1234)
wordcloud(words = topK$termino, freq = topK$frecuencia, min.freq = 1,
          max.words=200, random.order=FALSE, rot.per=0.35, 
          colors=brewer.pal(4, "Dark2"))
LS0tDQp0aXRsZTogImx5cmljcyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMgbGlicmVyaWFzDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkocmVzaGFwZSkNCmxpYnJhcnkocmVzaGFwZTIpDQpsaWJyYXJ5KG1vbmdvbGl0ZSkNCmxpYnJhcnkodGV4dGNhdCkNCmxpYnJhcnkodG0pDQpsaWJyYXJ5KHNlbnRpbWVudHIpDQpsaWJyYXJ5KHN0cmluZ3IpDQpsaWJyYXJ5KGFydWxlcykNCmBgYA0KDQoNCiMgQmFzZXMgZGUgbGV0cmFzIGZpbHRyYWRhcyBwb3IgaWRpb21hDQpgYGB7cn0NCiMgbHlyaWNzID0gbW9uZ28oY29sbGVjdGlvbiA9ICJseXJpY3MiLCBkYiA9ICJzcG90aWZ5X2RtIiApDQojIGRmX2x5cmljcyA8LSBseXJpY3MkZmluZCgne30nKQ0KIyANCiMgd3JpdGUuY3N2KGRmX2x5cmljcywgImRhdGEvZGZfbHlyaWNzLmNzdiIpDQoNCmRmX2x5cmljcyA8LSByZWFkLmNzdigiZGF0YS9kZl9seXJpY3MuY3N2IikgJT4lIA0KICBzZWxlY3QoLVgpDQoNCmRmX2x5cmljc191bmljYXMgPC0gZGZfbHlyaWNzICU+JSANCiAgZGlzdGluY3QoYXJ0aXN0X25hbWUsIHRyYWNrX25hbWUsIGx5cmljcykNCg0KDQojZmlsdHJvIGRlIGlkaW9tYQ0Kc3BhX2x5cmljcyA9IGRmX2x5cmljc191bmljYXNbdGV4dGNhdChkZl9seXJpY3NfdW5pY2FzJGx5cmljcyk9PSJzcGFuaXNoIixdDQpzcGFfbHlyaWNzDQoNCmVuX2x5cmljcyA9IGRmX2x5cmljc191bmljYXNbdGV4dGNhdChkZl9seXJpY3NfdW5pY2FzJGx5cmljcykgJWluJSBjKCJlbmdsaXNoIiwgInNjb3RzIiksXQ0KZW5fbHlyaWNzDQoNCiNjaGVxdWVvIGNhbnRpZGFkIGRlIGNhbmNpb25lcyBwb3IgaWRpb21hDQoxMDAqKG5yb3coZW5fbHlyaWNzKSArIG5yb3coc3BhX2x5cmljcykpL25yb3coZGZfbHlyaWNzX3VuaWNhcykNCg0KIyB0YWJsYSBjb250aW5nZW5jaWEgZGUgaWRpb21hcw0KaWRpb21hcyA9IHRleHRjYXQoZGZfbHlyaWNzX3VuaWNhcyRseXJpY3MpDQojIHNvcnQodGFibGUoaWRpb21hcyksIGRlY3JlYXNpbmcgPSBUKQ0KDQpgYGANCg0KIyBsaW1waWV6YSBlc3Bhw7FvbA0KYGBge3J9DQojIGNvbWVudGFyIHkgZGVzY29tZW50YXIgc2Vnw7puIHNlIGVsaWphIHVuIGRhdGFmcmFtZSB1IG90cm8NCiMgZGZfbHlyaWNzX3NlbGVjY2lvbmFkbyA9IGRmX2x5cmljc191bmljYXMNCmRmX2x5cmljc19zZWxlY2Npb25hZG8gPSBlbl9seXJpY3MNCg0KY29ycHVzID0gQ29ycHVzKFZlY3RvclNvdXJjZShlbmMydXRmOChkZl9seXJpY3Nfc2VsZWNjaW9uYWRvJGx5cmljcykpKQ0KDQojIEVsaW1pbmFtb3MgZXNwYWNpb3MNCmNvcnB1cy5wcm8gPC0gdG1fbWFwKGNvcnB1cywgc3RyaXBXaGl0ZXNwYWNlKQ0KaW5zcGVjdChjb3JwdXMucHJvWzFdKQ0KDQojIEVsaW1pbm8gdG9kbyBsbyBxdWUgYXBhcmVjZSBhbnRlcyBkZWwgcHJpbWVyIFtdDQpjb3JwdXMucHJvIDwtIHRtX21hcChjb3JwdXMucHJvLCBjb250ZW50X3RyYW5zZm9ybWVyKA0KICBmdW5jdGlvbih4KSBzdWIoJ14uKz9cXFsuKj9cXF0nLCIiLCB4KSkpDQojIGluc3BlY3QoY29ycHVzLnByb1sxXSkNCg0KIyBFbGltaW5vIGxhcyBhY2xhcmFjaW9uZXMgZW4gbGFzIGNhbmNpb25lcywgcG9yIGVqZW1wbG86DQojIFtWZXJzbyAxOiBMdWlzIEZvbnNpICYgRGFkZHkgWWFua2VlXQ0KY29ycHVzLnBybyA8LSB0bV9tYXAoY29ycHVzLnBybywgY29udGVudF90cmFuc2Zvcm1lcigNCiAgZnVuY3Rpb24oeCkgZ3N1YignXFxbLio/XFxdJywgJycsIHgpKSkNCg0KIyBFbGltaW5vIHRvZG8gbG8gcXVlIGFwYXJlY2UgbHVlZ28gZGUgJ01vcmUgb24gR2VuaXVzJw0KY29ycHVzLnBybyA8LSB0bV9tYXAoY29ycHVzLnBybywgY29udGVudF90cmFuc2Zvcm1lcihmdW5jdGlvbih4KSBnc3ViKCJNb3JlIG9uIEdlbml1cy4qIiwiIiwgeCkpKQ0KDQojIENvbnZlcnRpbW9zIGVsIHRleHRvIGEgbWluw7pzY3VsYXMNCmNvcnB1cy5wcm8gPC0gdG1fbWFwKGNvcnB1cy5wcm8sIGNvbnRlbnRfdHJhbnNmb3JtZXIodG9sb3dlcikpDQoNCiMgcmVtb3ZlbW9zIG7Dum1lcm9zDQpjb3JwdXMucHJvIDwtIHRtX21hcChjb3JwdXMucHJvLCByZW1vdmVOdW1iZXJzKQ0KDQojIFBvZGVtb3MgYWdyZWdhciBwYWxhYnJhcyBhIGxhcyBzdG9wd29yZHMNCiMgbXlfc3RvcHdvcmRzIDwtIGFwcGVuZChzdG9wd29yZHMoInNwYW5pc2giKSwgJ3BhbGFicmEnKQ0KbXlfc3RvcHdvcmRzIDwtIGFwcGVuZChzdG9wd29yZHMoImVuZ2xpc2giKSwgYygneWVhaCcsICJhaW50IiwgImdldCIsICJnb3QiKSkNCg0KIyBSZW1vdmVtb3MgcGFsYWJyYXMgdmFjaWFzIA0KY29ycHVzLnBybyA8LSB0bV9tYXAoY29ycHVzLnBybywgcmVtb3ZlV29yZHMsIHN0b3B3b3JkcygiZW5nbGlzaCIpKQ0KY29ycHVzLnBybyA8LSB0bV9tYXAoY29ycHVzLnBybywgcmVtb3ZlV29yZHMsIG15X3N0b3B3b3JkcykNCiMgY29ycHVzLnBybyA8LSB0bV9tYXAoY29ycHVzLnBybywgcmVtb3ZlV29yZHMsIHN0b3B3b3Jkcygic3BhbmlzaCIpKQ0KIyBpbnNwZWN0KGNvcnB1cy5wcm9bMV0pDQoNCg0KIyBSZW1vdmVtb3MgcHVudHVhY2lvbmVzDQpjb3JwdXMucHJvIDwtIHRtX21hcChjb3JwdXMucHJvLCByZW1vdmVQdW5jdHVhdGlvbikNCg0KIyBSZW1vdmVtb3MgdG9kbyBsbyBxdWUgbm8gZXMgYWxmYW51bcOpcmljbw0KY29ycHVzLnBybyA8LSB0bV9tYXAoY29ycHVzLnBybywgY29udGVudF90cmFuc2Zvcm1lcihmdW5jdGlvbih4KSBzdHJfcmVwbGFjZV9hbGwoeCwgIltbOnB1bmN0Ol1dIiwgIiAiKSkpDQoNCiMgRW4gdG1fbWFwIHBvZGVtb3MgdXRpbGl6YXIgZnVuY2lvbmVzIHByb3ANCmxpYnJhcnkoc3RyaW5naSkNCnJlcGxhY2VBY2VudG9zIDwtIGZ1bmN0aW9uKHgpIHtzdHJpX3RyYW5zX2dlbmVyYWwoeCwgIkxhdGluLUFTQ0lJIil9DQpjb3JwdXMucHJvIDwtIHRtX21hcChjb3JwdXMucHJvLCByZXBsYWNlQWNlbnRvcykNCg0KIyBFbGltaW5hbW9zIGVzcGFjaW9zIHF1ZSBzZSB2YW4gZ2VuZXJhbmRvIGNvbiBsb3MgcmVlbXBsYXpvcw0KY29ycHVzLnBybyA8LSB0bV9tYXAoY29ycHVzLnBybywgc3RyaXBXaGl0ZXNwYWNlKQ0KYGBgDQoNCiMgbGltcGllemEgaW5nbGVzDQpgYGB7cn0NCiNmdW5jaW9uZXMNCiNmdW5jaW9uIHBhcmEgY29ycmVnaXIgcGFsYWJyYXMNCmRlY29udHJhY3RlZCA9IGZ1bmN0aW9uKHR4dCl7DQogIHR4dCA9IGdzdWIoIndvbid0IiwgIndpbGwgbm90IiwgdHh0KQ0KICB0eHQgPSBnc3ViKCJcXCdzIiwgIiBpcyIsIHR4dCkNCiAgdHh0ID0gZ3N1YigiXFwndCIsICIgbm90IiwgdHh0KQ0KICB0eHQgPSBnc3ViKCJcXCdsbCIsICIgd2lsbCIsIHR4dCkNCiAgdHh0ID0gZ3N1YigiXFwnbSIsICIgYW0iLCB0eHQpDQogIHR4dCA9IGdzdWIoIlxcJ3JlIiwgIiBhcmUiLCB0eHQpDQogIHR4dCA9IGdzdWIoIlxcJ2QiLCAiIGhhZCIsIHR4dCkNCiAgdHh0ID0gZ3N1YigiXFwndmUiLCAiIGhhdmUiLCB0eHQpDQogIHR4dCA9IGdzdWIoImNvdWxkbiIsICJjb3VsZCIsIHR4dCkNCiAgdHh0ID0gZ3N1YigiZG9uIiwgImRvIiwgdHh0KQ0KICB0eHQgPSBnc3ViKCJkb2VzbiIsICJkb2VzIiwgdHh0KQ0KICB0eHQgPSBnc3ViKCJpc24iLCAiaXMiLCB0eHQpDQogIHR4dCA9IGdzdWIoIm11c3RuIiwgIm11c3QiLCB0eHQpDQogIHR4dCA9IGdzdWIoInNob3VsZG4iLCAic2hvdWxkIiwgdHh0KQ0KICB0eHQgPSBnc3ViKCJ3YXNuIiwgIndhcyIsIHR4dCkNCiAgdHh0ID0gZ3N1YigiXFwnY2F1c2UiLCAiIGJlY2F1c2UiLCB0eHQpDQogIHR4dCA9IGdzdWIoIlxcJyIsICJnIiwgdHh0KQ0KICByZXR1cm4odHh0KQ0KfQ0KDQoNCiNGdW5jacOzbiBwYXJhIGxpbXBpYXIuIA0KdGV4dF9jbGVhbmluZyA9IGZ1bmN0aW9uKHR4dCwgc3RvcD1GQUxTRSwgbGFuZ3VhZ2Upew0KICANCiAgdHh0ID0gc3ViKCdeLis/XFxbLio/XFxdJywiIiwgdHh0KSAjb2sNCiAgdHh0ID0gc3ViKCJNb3JlIG9uIEdlbml1cy4qIiwiIiwgdHh0KQ0KICB0eHQgPSBnc3ViKCdcXFsuKj9cXF0nLCAnJywgdHh0KQ0KICB0eHQgPSBnc3ViKCJcXG4iLCIgIiwgdHh0KQ0KICB0eHQgPSBnc3ViKCJbKCldIiwgIiAiLCB0eHQpDQogIHR4dCA9IHRvbG93ZXIodHh0KQ0KICB0eHQgPSBkZWNvbnRyYWN0ZWQodHh0KQ0KICB0eHQgPSBnc3ViKCJcXFcrXFxiIiwgIiAiLCB0eHQpDQogIHR4dCA9IGdzdWIoIlxcZCIsICIgIiwgdHh0KQ0KICANCiAgc3RvcHdvcmRzX3JlZ2V4ID0gcGFzdGUoc3RvcHdvcmRzKCdlbicpLCBjb2xsYXBzZSA9ICdcXGJ8XFxiJykNCiAgc3RvcHdvcmRzX3JlZ2V4ID0gcGFzdGUwKCdcXGInLCBzdG9wd29yZHNfcmVnZXgsICdcXGInKQ0KICB0eHQgPSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwodHh0LCBzdG9wd29yZHNfcmVnZXgsICcnKQ0KDQogIG15X3N0b3B3b3JkcyA8LSBjKCdvb2gnLCAneWVhaCcsICJhaW50IiwgImdldCIsICJnb3QiLCAiYXl5IikNCiAgdHh0ID0gc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKHR4dCwgbXlfc3RvcHdvcmRzLCAnJykNCiAgIA0KICB0eHQgPSBzdHJfdHJpbSh0eHQpDQogIHR4dCA9IGdzdWIoIlxcbiIsIiAiLCB0eHQpDQogIA0KICBpZihsYW5ndWFnZSA9PSAiZW4iKXsNCiAgICByZXR1cm4odHh0KQ0KICB9ZWxzZSBpZiAobGFuZ3VhZ2UgPT0gImVzIil7DQogICAgdHh0IDwtIGZ1bmN0aW9uKHgpIHtzdHJpX3RyYW5zX2dlbmVyYWwoeCwgIkxhdGluLUFTQ0lJIil9DQogICAgICByZXR1cm4odHh0KSANCiAgfWVsc2V7DQogICAgICAgIHJldHVybigiRmFsdGEgZGVmaW5pciBsZW5ndWFqZSIpDQogICAgICB9DQp9DQoNCiNmdW5jacOzbiBwYXJhIG9idGVuZXIgb3JhY2lvbmVzIGRlIHVuYSBzb2xhIHBhbGFicmEuIA0Kb25lX3dvcmRfc2V0ZW5jZXMgPSBmdW5jdGlvbih0eHQpew0KICByZXR1cm4oZ3N1YigiXFxXK1xcYiIsICIuICIsIHR4dCkpDQp9DQoNCiNsaW1waW8gbGFzIGxldHJhcyBlbiBpbmdsZXMNCmVuX2x5cmljcyRseXJpY3MgPSB0ZXh0X2NsZWFuaW5nKGVuX2x5cmljcyRseXJpY3MsIGxhbmd1YWdlID0gImVuIikNCg0KaGVhZChlbl9seXJpY3MkbHlyaWNzLCAxKQ0KDQoNCmBgYA0KDQoNCg0KIyBFeHBsaWNpdA0KIyMgRXNwYcOxb2wNCmBgYHtyfQ0KI0RpY2Npb25hcmlvIGVzcGHDsW9sDQptYWxhc19wYWxhYnJhc18xIDwtIHJlYWRfY3N2KCJkYXRhL21hbGFzX3BhbGFicmFzLnR4dCIsIA0KICAgIGNvbF9uYW1lcyA9IEZBTFNFKQ0KDQptYWxhc19wYWxhYnJhc18yIDwtIHJlYWRfY3N2KCJkYXRhL21hbGFzX3BhbGFicmFzX3RyYW5zbGF0ZS50eHQiLCANCiAgICBjb2xfbmFtZXMgPSBGQUxTRSkNCg0KbWFsYXNfcGFsYWJyYXNfMyA8LSByZWFkX2NzdigiZGF0YS9tYWxhc19wYWxhYnJhc193aWtpLnR4dCIsIA0KICAgIGNvbF9uYW1lcyA9IEZBTFNFKSAlPiUgDQogIHNlbGVjdChYMSkNCg0KbWFsYXNfcGFsYWJyYXNfNCA8LSByZWFkX2NzdigiZGF0YS9wYWxhYnJhc19wcm9mYW5hc19lcy50eHQiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sX25hbWVzID0gRkFMU0UpDQoNCm1hbGFzX3BhbGFicmFzIDwtIHJiaW5kKG1hbGFzX3BhbGFicmFzXzEsIG1hbGFzX3BhbGFicmFzXzIsDQogICAgICAgICAgICAgICAgICAgICAgICBtYWxhc19wYWxhYnJhc18zLCBtYWxhc19wYWxhYnJhc180KQ0KDQoNCiNGdW5jacOzbiBwYXJhIGxpbXBpYXIuIA0KdGV4dF9jbGVhbmluZ19lc3AgPSBmdW5jdGlvbih0eHQsIHN0b3A9RkFMU0Upew0KICB0eHQgPSBzdWIoJ14uKz9cXFsuKj9cXF0nLCIiLCB0eHQpICNvaw0KICB0eHQgPSBzdWIoIk1vcmUgb24gR2VuaXVzLioiLCIiLCB0eHQpDQogIHR4dCA9IGdzdWIoJ1xcWy4qP1xcXScsICcnLCB0eHQpDQogIHR4dCA9IGdzdWIoIlxcbiIsIiAiLCB0eHQpDQogIHR4dCA9IGdzdWIoIlsoKV0iLCAiICIsIHR4dCkNCiAgdHh0ID0gdG9sb3dlcih0eHQpDQogICMgdHh0ID0gZGVjb250cmFjdGVkKHR4dCkNCiAgdHh0ID0gZ3N1YigiXFxXK1xcYiIsICIgIiwgdHh0KQ0KICB0eHQgPSBnc3ViKCJcXGQiLCAiICIsIHR4dCkNCiAgdHh0ID0gc3RyX3RyaW0odHh0KQ0KICAjIHR4dCA9IHN0cmlfdHJhbnNfZ2VuZXJhbCh0eHQsICJMYXRpbi1BU0NJSSIpDQogIHJldHVybih0eHQpDQp9DQoNCg0KbWFsYXNfcGFsYWJyYXMkbGltcGlhcyA9IHRleHRfY2xlYW5pbmcobWFsYXNfcGFsYWJyYXMkWDEpDQptYWxhc19wYWxhYnJhcw0KDQptYWxhc19wYWxhYnJhcyAlPiUgZmlsdGVyKHN0YXJ0c1dpdGgobGltcGlhcywgImciKSkNCg0KYGBgDQoNCiMjIEluZ2zDqXMNCmBgYHtyfQ0KI0dlbmVybyBsaXN0YSBkZSBtYWxhcyBwYWxhYnJhcw0KYmFkX3dvcmRzIDwtIGMoKQ0KYmFkX3dvcmRzIDwtIGFwcGVuZChiYWRfd29yZHMsIHVuaXF1ZSh0b2xvd2VyKGxleGljb246OnByb2Zhbml0eV96YWNfYW5nZXIpKSkNCmJhZF93b3JkcyA8LSBhcHBlbmQoYmFkX3dvcmRzLCB1bmlxdWUodG9sb3dlcihsZXhpY29uOjpwcm9mYW5pdHlfYWx2YXJleikpKQ0KYmFkX3dvcmRzIDwtIGFwcGVuZChiYWRfd29yZHMsIHVuaXF1ZSh0b2xvd2VyKGxleGljb246OnByb2Zhbml0eV9hcnJfYmFkKSkpDQpiYWRfd29yZHMgPC0gYXBwZW5kKGJhZF93b3JkcywgdW5pcXVlKHRvbG93ZXIobGV4aWNvbjo6cHJvZmFuaXR5X3JhY2lzdCkpKQ0KYmFkX3dvcmRzIDwtIGFwcGVuZChiYWRfd29yZHMsIHVuaXF1ZSh0b2xvd2VyKGxleGljb246OnByb2Zhbml0eV9iYW5uZWQpKSkNCmJhZF93b3JkcyA8LSB1bmlxdWUoYmFkX3dvcmRzKQ0KDQpiaWdsb3UgPC0gcmVhZC5jc3YoImh0dHBzOi8vd3d3LmNzLmNtdS5lZHUvfmJpZ2xvdS9yZXNvdXJjZXMvYmFkLXdvcmRzLnR4dCIsIGhlYWRlcj1GQUxTRSwgY29sLm5hbWVzID0gYygid29yZHMiKSkNCg0KDQojRnVuY2nDs24gcGFyYSBvYnRlbmVyIHBhbGFicmFzIHByb2ZhbmFzIGRlIGNhZGEgbHlyaWMNCmdldF9wcm9mYW5pdGllcyA9IGZ1bmN0aW9uKHR4dCwgcHJvZmFuaXR5X2xzdCl7DQogICMgdHh0ID0gdGV4dF9jbGVhbmluZyh0eHQpDQogIHdvcmRzID0gYXMuZGF0YS5mcmFtZShzdHJzcGxpdCh0eHQsICJbIF0rIiksIGNvbC5uYW1lcyA9ICJ3b3JkcyIpDQogIHByb2Zhbl9kZiA9IHByb2Zhbml0eShnZXRfc2VudGVuY2VzKHdvcmRzKSwgcHJvZmFuaXR5X2xpc3QgPSBwcm9mYW5pdHlfbHN0KQ0KICBwcm9mYW5fd29yZHMgPSBwcm9mYW5fZGZbcHJvZmFuX2RmJHByb2Zhbml0eV9jb3VudCE9MCxdJHdvcmRzDQogIHZlY3RvciA9IGFzLnZlY3Rvcihwcm9mYW5fd29yZHMpDQogIGlmIChsZW5ndGgodmVjdG9yKT09MCl7DQogICAgcmV0dXJuKE5VTEwpDQogIH0NCiAgZWxzZXtyZXR1cm4oYXMudmVjdG9yKHByb2Zhbl93b3JkcykpDQogICAgfQ0KfQ0KDQoNCg0KZW5fbHlyaWNzJHByb2ZhYmVfYmlnbG91IDwtIGxhcHBseShlbl9seXJpY3MkbHlyaWNzLCAgZnVuY3Rpb24oeCkgZ2V0X3Byb2Zhbml0aWVzKHgsIGJpZ2xvdSR3b3JkcykpDQoNCmVuX2x5cmljcyAlPiUgDQogIG11dGF0ZShwcm9mYW5lX2JpZ2xvdSA9IHVubGlzdChnZXRfcHJvZmFuaXRpZXMobHlyaWNzLCBiaWdsb3Ukd29yZHMpKSkNCg0KZW5fbHlyaWNzJHByb2ZhYmVfYmlnbG91ID0gdW5saXN0KHN0cnNwbGl0KGVuX2x5cmljcyRwcm9mYWJlX2JpZ2xvdSwgc3BsaXQgPSAiICIpKQ0KDQplbl9seXJpY3MkcHJvZmFiZV9iYWR3b3JkcyA8LSBsYXBwbHkoZW5fbHlyaWNzJGx5cmljcywgZnVuY3Rpb24oeCkgZ2V0X3Byb2Zhbml0aWVzKHgsIGJhZF93b3JkcykpDQoNCnN0cihlbl9seXJpY3MpDQpoZWFkKGVuX2x5cmljcywxKQ0KDQplbl9seXJpY3MkcHJvZmFiZV9iaWdsb3VbM10NCg0KYGBgDQoNCg0KIyBtYXRyaXogdMOpcm1pbm8gZG9jdW1lbnRvDQpgYGB7cn0NCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojIyMjIyMjIEdlbmVyYWNpw7NuIGRlIGxhIE1hdHLDrXogVMOpcm1pbm8tRG9jdW1lbnRvIGRlbCBjb3JwdXMgIyMjIyMjIw0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCmNvcnB1cy5wcm8ydGRtIDwtIGZ1bmN0aW9uKGNvcnB1cywgcG9uZGVyYWNpb24sIG5fdGVybXMpew0KICAjY29ycHVzDQogIA0KICANCiAgI21hdHJpeiBURCANCiAgZHRtIDwtIFRlcm1Eb2N1bWVudE1hdHJpeChjb3JwdXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3Qod2VpZ2h0aW5nID0gcG9uZGVyYWNpb24pKQ0KICBtYXRyaXpfdGQgPC0gYXMubWF0cml4KGR0bSkNCiAgDQogIA0KICAjIENhbGN1bGFtb3MgbGEgZnJlY3VlbmNpYSBkZSBjYWRhIHTDqXJtaW5vIGVuIGVsIGNvcnB1cw0KICBmcmVxX3Rlcm0gPC0gaGVhZChzb3J0KHJvd1N1bXMobWF0cml6X3RkKSxkZWNyZWFzaW5nPVRSVUUpLCBuX3Rlcm1zKQ0KICANCiAgI21hdHJpeiB0cmFuc3B1ZXN0YSBkZSBsb3Mgbl90ZXJtcyBtYXMgZnJlY3VlbnRlcw0KICBtYXRyaXpfbmYgPC0gdChtYXRyaXpfdGRbc29ydChuYW1lcyhmcmVxX3Rlcm0pKSwgXSkNCiAgDQogICNwYXNhamUgYSBiaW5hcmlvDQogIG1hdHJpel9uZlttYXRyaXpfbmY+MF0gPC0gMQ0KICANCiAgcmV0dXJuKG1hdHJpel9uZikNCiAgDQogIH0NCiAgDQpjb3JwdXNfZW5nID0gQ29ycHVzKFZlY3RvclNvdXJjZShlbmMydXRmOChlbl9seXJpY3MkbHlyaWNzKSkpDQptYXRyaXogPC0gY29ycHVzLnBybzJ0ZG0oY29ycHVzID0gY29ycHVzX2VuZywgcG9uZGVyYWNpb249ICJ3ZWlnaHRUZiIsbl90ZXJtcz0gMTUwKQ0KDQpkaW0obWF0cml6KQ0KDQpkZl90bSA8LSBhcy5kYXRhLmZyYW1lKG1hdHJpeikNCmhlYWQoZGZfdG0sMikNCg0KIyMgSm9pbiBtYXRyaXogZGUgcGFsYWJyYXMgY29uIGFydGlzdGEgeSB0cmFjaw0KZGZfbHlfZmVhdCA8LSBjYmluZChkZl9seXJpY3Nfc2VsZWNjaW9uYWRvWy1jKDMpXSwgZGZfdG0pDQoNCm5yb3coZGZfdG0pDQpucm93KGRmX2x5cmljc19zZWxlY2Npb25hZG8pDQpucm93KGRmX2x5X2ZlYXQpDQoNCmZpbHRlciA8LSAhbmFtZXMoZGZfbHlfZmVhdCkgJWluJSBjKCJhcnRpc3RfbmFtZSIsICJ0cmFja19uYW1lIiApDQoNCmRmX2x5X2ZlYXRfb2sgPC0gZGZfbHlfZmVhdFssIGZpbHRlcl0NCiMgZGZfbHlfZmVhdF9vayA9IGRmX2x5X2ZlYXRfb2tbLCAtKHdoaWNoKGNvbFN1bXMoZGZfbHlfZmVhdF9vaykgPT0gMCkpXQ0KDQojIGNvbFN1bXMoZGZfbHlfZmVhdF9vaykNCg0KaGVhZChkZl9seV9mZWF0X29rLCAzKQ0KaGVhZChkZl9seV9mZWF0LCAzKQ0KDQoNCmRmX2x5X2ZlYXQkaWQgPSAxOm5yb3coZGZfbHlfZmVhdCkNCg0KZGZfbWVsdCA8LSByZXNoYXBlMjo6bWVsdChkYXRhID0gZGZfbHlfZmVhdFssMzpuY29sKGRmX2x5X2ZlYXQpXSwgaWQudmFycyA9IGMoImlkIikpICAlPiUNCiAgYXJyYW5nZShpZCkNCg0KZGZfbWVsdCA8LSBkZl9tZWx0W2RmX21lbHQkdmFsdWUgIT0gMCxdDQoNCmRmX21lbHRfdHh0IDwtIGRmX21lbHRbZGZfbWVsdCR2YWx1ZSA9PSAxLF0NCmRmX21lbHRfY2F0IDwtIGRmX21lbHRbZGZfbWVsdCR2YWx1ZSAhPSAxLF0NCg0KaGVhZChkZl9tZWx0X3R4dCApDQpkaW0oZGZfbWVsdF90eHQgKQ0KDQojZGVub21pbm8gYSBsb3MgdMOpcm1pbm9zIHByb2Zhbm9zDQpkZl9tZWx0X3R4dCA8LSBkZl9tZWx0X3R4dCAlPiUgDQogIG11dGF0ZSh2YXJpYWJsZSA9IGNhc2Vfd2hlbihhcy5jaGFyYWN0ZXIodmFyaWFibGUpICVpbiUgYmlnbG91JHdvcmRzIH4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKCJQUk9GXyIsIGFzLmNoYXJhY3Rlcih2YXJpYWJsZSkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVCB+IHBhc3RlMCgiVEVSTV8iLCBhcy5jaGFyYWN0ZXIodmFyaWFibGUpKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSAgDQogICAgICAgICApDQoNCmRmX21lbHRfdHh0ICU+JSBmaWx0ZXIoc3RhcnRzV2l0aCh2YXJpYWJsZSwgIlBST0YiKSkNCg0KDQojIGRmX21lbHRfdHh0W2RmX21lbHRfdHh0JHZhcmlhYmxlICVpbiUgYmlnbG91JHdvcmRzLF0NCg0KDQpkZl9tZWx0X3R4dF90b19ydWxzIDwtIGRmX21lbHRfdHh0WywgLWMoMyldDQpuYW1lcyhkZl9tZWx0X3R4dF90b19ydWxzKSA8LSBjKCJpZCIsICJpdGVtIikNCg0Kd3JpdGUudGFibGUoZGZfbWVsdF90eHRfdG9fcnVscywgZmlsZT0iZGF0YS90cmFuc2FjY2lvbnNfbHlyaWNzX2ZlYXR1cmVzLnR4dCIsIHJvdy5uYW1lcyA9IEYpDQoNCiMgUmVnbGFzDQojIGNoZXF1ZWFyIG5hbidzDQpseXJpY3NfdHJhbnMgPC0gcmVhZC50cmFuc2FjdGlvbnMoImRhdGEvdHJhbnNhY2Npb25zX2x5cmljc19mZWF0dXJlcy50eHQiLCBmb3JtYXQgPSAic2luZ2xlIiwgY29scyA9IGMoMSwyKSkNCg0KYXJ1bGVzOjppbnNwZWN0KGhlYWQobHlyaWNzX3RyYW5zLCAzKSkNCg0Kc3VtbWFyeShseXJpY3NfdHJhbnMpDQpyZWdsYXMgPC0gYXByaW9yaShseXJpY3NfdHJhbnMsIHBhcmFtZXRlciA9IGxpc3Qoc3VwcG9ydD0wLjEsDQogICAgICAgICAgICAgICAgICAgIGNvbmZpZGVuY2UgPSAwLjUsIHRhcmdldCAgPSAicnVsZXMiICApKQ0KDQpyZWdsYXNfc3ViIDwtIHN1YnNldChyZWdsYXMsIHN1YnNldCA9IHJocyAlcGluJSAiUFJPRl8iKQ0KYXJ1bGVzOjppbnNwZWN0KGhlYWQoc29ydChyZWdsYXNfc3ViLCBieSA9ICJsaWZ0IiwgZGVjcmVhc2luZyA9IFQpLDUpKQ0KDQpgYGANCg0KDQoNCiMgZnJlY3VlbmNpYSBkZSB0w6lybWlub3MNCmBgYHtyfQ0KIyBEYXRhZnJhbWUgY29uIGZyZWN1ZW5jaWEgZGUgdGVybWlub3MgKGRlIHJvd3MpDQpkdG1fdG9fZnJlcSA8LSBUZXJtRG9jdW1lbnRNYXRyaXgoY29ycHVzLnBybywgY29udHJvbCA9IGxpc3Qod2VpZ2h0aW5nID0gICJ3ZWlnaHRUZiIpKQ0KbWF0cml6X3RkX3RvX2ZyZXEgPC0gYXMubWF0cml4KGR0bV90b19mcmVxKQ0KZnJlcV90ZXJtIDwtIHNvcnQocm93U3VtcyhtYXRyaXpfdGRfdG9fZnJlcSksIGRlY3JlYXNpbmc9VFJVRSApDQpkZl9mcmVxIDwtIGRhdGEuZnJhbWUodGVybWlubyA9IG5hbWVzKGZyZXFfdGVybSksIGZyZWN1ZW5jaWE9ZnJlcV90ZXJtKQ0Kcm93Lm5hbWVzKGRmX2ZyZXEpIDwtIE5VTEwNCmhlYWQoZGZfZnJlcSkNCg0KDQojIyBHcmFmaWNvcyBkZSB0ZXJtaW5vcw0KTj0xNQ0KYmFycGxvdChkZl9mcmVxWzE6TixdJGZyZWN1ZW5jaWEsIGxhcyA9IDIsIG5hbWVzLmFyZyA9IGRmX2ZyZXFbMTpOLF0kdGVybWlubywNCiAgICAgICAgY29sID0ibGlnaHRibHVlIiwgbWFpbiA9IlBhbGFicmFzIG3DoXMgZnJlY3VlbnRlcyIsDQogICAgICAgIHlsYWIgPSAiRnJlY3VlbmNpYSBkZSBwYWxhYnJhcyIsIHlsaW0gPSBjKDAsIG1heChkZl9mcmVxJGZyZWN1ZW5jaWEpKzMwMCkpDQoNCg0KdG9wSyA9IGhlYWQoZGZfZnJlcSwgMTAwKQ0KDQojIFZpc3VhbGl6YWNpw7NuIGRlIGxvcyByZXN1bHRhZG9zDQojIE51YmUgZGUgRXRpcXVldGFzDQpsaWJyYXJ5KCJ3b3JkY2xvdWQiKQ0KbGlicmFyeSgiUkNvbG9yQnJld2VyIikNCg0KcGFyKGJnPSJncmV5MzAiKSAjIEZpamFtb3MgZWwgZm9uZG8gZW4gY29sb3IgZ3Jpcw0KDQpzZXQuc2VlZCgxMjM0KQ0Kd29yZGNsb3VkKHdvcmRzID0gdG9wSyR0ZXJtaW5vLCBmcmVxID0gdG9wSyRmcmVjdWVuY2lhLCBtaW4uZnJlcSA9IDEsDQogICAgICAgICAgbWF4LndvcmRzPTIwMCwgcmFuZG9tLm9yZGVyPUZBTFNFLCByb3QucGVyPTAuMzUsIA0KICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDQsICJEYXJrMiIpKQ0KDQoNCg0KYGBgDQoNCg0K